import re as regex
import string, UserDict
# Special keys - leading space for sort to front 
DefaultSect = ' _global_'
DefaultOpt = ' _values_'
Comments = ' _comments_'

class IniFile(UserDict.UserDict):
    """ Invoke with name of .ini file """
    _section = regex.compile(r"^\[(.+)\]")
    _option    = regex.compile(r"^([^ \t]+)[ \t]*=[ \t]*(.*)$")
        
    def __init__(self, fn):
        self.filename = fn
        self.data = {}
        # Parse the .ini file
        try:
            f = open(fn)
            lines = filter(None, f.readlines())
            f.close()
        except:
            lines = []

        sect = DefaultSect
        self.data[sect] = {}
        opt = None

        for line in lines:
            line = string.rstrip(line)
            if line == '':
                opt = None
                continue

            if line[0] == ';' or line[0] == '#':
                if not self.data[sect].has_key(Comments):
                    self.data[sect][Comments] = []
                self.data[sect][Comments].append(line)
                continue
            m = self._section.match(line)
            if m != None:
                sect = m.group(1)
                if not self.data.has_key(sect):
                    self.data[sect] = {}
                opt = None
                continue
            m = self._option.match(line)
            if m != None:
                opt, val = m.group(1, 2)
                self.data[sect][opt] = val
                continue

            if opt and line[0] == '\t':
                self.data[sect][opt] = '%s %s' \
                    % (self.data[sect][opt], string.lstrip(line))
                continue

            if not self.data[sect].has_key(DefaultOpt):
                self.data[sect][DefaultOpt] = []
            self.data[sect][DefaultOpt].append(line)
            opt = None

        if not self.data[DefaultSect]:
            del self.data[DefaultSect]


    def change(self, name, value, section):
        """ Change value of old 'name', or add new """
        # See if name already exists in default section
        data = self.data
        for sect in (section, DefaultSect):
            if data.has_key(sect) and data[sect].has_key(name):
                section = sect
                break
        else:
            if not data.has_key(section):
                data[section] = {}

        data[section][name] = value

    def write(self):
        """ Write the data back to the file """
        f = open(self.filename, "w")
        sections = self.data.keys()
        sections.sort()
        for section in sections:
            if section is not DefaultSect:
                f.write('\n[%s]\n' % section)
            data = self.data[section]
            names = data.keys()
            names.sort()

            for name in names:
                value = data[name]
                if name in (Comments, DefaultOpt):
                    f.write('%s\n' % string.join(value, '\n'))
                else:
                    f.write('%s = %s\n' % (name, value))
        f.close()
